diff --git a/README.md b/README.md
index 6392aef..dd0ccb0 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
A third party Telegram client library [danog/MadelineProto](https://github.com/danog/MadelineProto) wrapper for Laravel.
-# Usage
+# Getting Started
Add the laravel-madeline-proto to the project dependency:
@@ -13,7 +13,7 @@ Add the laravel-madeline-proto to the project dependency:
composer require setiawanhu/laravel-madeline-proto
```
-Then publish the telegram config file:
+Then publish the `telegram.php` config file:
```shell script
php artisan vendor:publish --provider="Hu\MadelineProto\MadelineProtoServiceProvider"
@@ -26,14 +26,11 @@ MP_TELEGRAM_API_ID=... //your telegram api id here
MP_TELEGRAM_API_HASH=... //your telegram api hash here
```
-To do a login:
+This wrapper package supports for running both [single](https://github.com/setiawanhu/laravel-madeline-proto/wiki/Single-Telegram-Account) / [multiple](https://github.com/setiawanhu/laravel-madeline-proto/wiki/Multiple-Telegram-Account) telegram account.
-* call `MadelineProto::phoneLogin(string $phone)` method to send the phone code.
+## Dig Deeper
-* call `MadelineProto::completePhoneLogin(string $code)` to complete the phone login by providing the phone code sent by the telegram.
-
-* You're logged in! Now you can use the `Messages` api.
-
+Please check [wiki](https://github.com/setiawanhu/sanctum-auth/wiki) for more details about laravel-madeline-proto usage
# Notes
diff --git a/composer.json b/composer.json
index 5252628..d9e94bb 100644
--- a/composer.json
+++ b/composer.json
@@ -2,7 +2,7 @@
"name": "setiawanhu/laravel-madeline-proto",
"description": "A third party Telegram client library danog/MadelineProto wrapper for Laravel",
"type": "library",
- "license": "GPL-2.0-only",
+ "license": "AGPL-3.0-only",
"authors": [
{
"name": "Setiawan Hu",
@@ -13,7 +13,8 @@
"php": "^7.4",
"danog/madelineproto": "^5.1",
"illuminate/support": "^7.0",
- "illuminate/console": "^7.0"
+ "illuminate/console": "^7.0",
+ "illuminate/database": "^7.0"
},
"autoload": {
"psr-4": {
diff --git a/config/telegram.php b/config/telegram.php
index 081dadf..73eb5a1 100644
--- a/config/telegram.php
+++ b/config/telegram.php
@@ -6,7 +6,7 @@ return [
/*
|--------------------------------------------------------------------------
- | Madeline Proto Session File Location
+ | Madeline Proto Sessions
|--------------------------------------------------------------------------
|
| To store information about an account session and avoid re-logging in, serialization must be done.
@@ -15,9 +15,21 @@ return [
| and on shutdown. If the scripts shutdowns normally (without ctrl+c or fatal errors/exceptions), the
| session will also be serialized automatically.
|
+ | Types: "single", "multiple"
+ |
*/
- 'session_file' => env('MADELINE_PROTO_SESSION_FILE', 'session.madeline'),
+ 'sessions' => [
+
+ 'single' => [
+ 'session_file' => env('MP_SESSION_FILE', 'session.madeline'),
+ ],
+
+ 'multiple' => [
+ 'table' => 'telegram_sessions'
+ ],
+
+ ],
/*
|--------------------------------------------------------------------------
@@ -37,15 +49,15 @@ return [
'logger' => Logger::FILE_LOGGER,
- 'logger_param' => storage_path('logs/madeline-proto.log'),
+ 'logger_param' => env('MP_LOGGER_PATH', storage_path('logs/madeline-proto.log')),
],
'app_info' => [
- 'api_id' => env('TELEGRAM_API_ID'),
+ 'api_id' => env('MP_TELEGRAM_API_ID'),
- 'api_hash' => env('TELEGRAM_API_HASH'),
+ 'api_hash' => env('MP_TELEGRAM_API_HASH'),
],
],
diff --git a/src/Commands/MultiSessionCommand.php b/src/Commands/MultiSessionCommand.php
new file mode 100644
index 0000000..d9a498c
--- /dev/null
+++ b/src/Commands/MultiSessionCommand.php
@@ -0,0 +1,141 @@
+option('model')) {
+ $user = $this->ask('Telegram user model (for relation)', 'App/User');
+
+ if (file_exists(app_path()) && !$this->option('force')) {
+ if (!$this->confirm("The App/TelegramSession model is already exist. Replace it?")) {
+ $this->info('Multi session export aborted.');
+ return;
+ }
+ }
+
+ $this->exportModel($user);
+
+ $this->info('TelegramSession model generated.');
+ }
+
+ $tableName = config('telegram.sessions.multiple.table');
+ $migration = "2020_08_12_000000_create_{$tableName}_table.php";
+
+ if (file_exists(database_path("migrations/$migration")) && !$this->option('force')) {
+ if (!$this->confirm("The {$migration} migration file is already exist. Replace it?")) {
+ $this->info('Multi session export aborted.');
+ return;
+ }
+ }
+
+ $this->exportMigration($tableName, $user ?? null);
+
+ $this->info('Migration file exported.');
+ }
+
+ /**
+ * Export the telegram_session migration file.
+ *
+ * @param string $tableName
+ * @param string|null $relation
+ */
+ public function exportMigration(string $tableName, string $relation = null)
+ {
+ if ($relation == null) {
+ $relation = 'App/User';
+ }
+
+ file_put_contents(
+ database_path("migrations/2020_08_12_000000_create_{$tableName}_table.php"),
+ $this->compileMigrationStub($tableName, $relation)
+ );
+ }
+
+ /**
+ * Export the TelegramSession model file.
+ *
+ * @param string $relation
+ */
+ public function exportModel(string $relation)
+ {
+ file_put_contents(
+ app_path('TelegramSession.php'),
+ $this->compileModelStub($relation)
+ );
+ }
+
+ /**
+ * Compile the TelegramSession stub.
+ *
+ * @param string $user
+ * @return string
+ */
+ public function compileModelStub(string $user)
+ {
+ $stub = file_get_contents(__DIR__ . '/stubs/telegram_session.stub');
+ $namespace = str_replace(
+ "/" . class_basename($user),
+ "",
+ $user
+ );
+
+ return str_replace(
+ ['{{user}}', '{{package}}'],
+ [Str::snake(class_basename($user)), $namespace],
+ $stub
+ );
+ }
+
+ /**
+ * Compile the TelegramSession migration stub.
+ *
+ * @param string $tableName
+ * @param string $user
+ * @return string
+ */
+ public function compileMigrationStub(string $tableName, string $user)
+ {
+ return str_replace(
+ ['{{table}}', '{{user}}'],
+ [$tableName, Str::snake(class_basename($user))],
+ file_get_contents(__DIR__ . '/stubs/migration.stub')
+ );
+ }
+}
diff --git a/src/Commands/TelegramAccountLoginCommand.php b/src/Commands/TelegramAccountLoginCommand.php
index d85f50f..1a083a2 100644
--- a/src/Commands/TelegramAccountLoginCommand.php
+++ b/src/Commands/TelegramAccountLoginCommand.php
@@ -34,12 +34,12 @@ class TelegramAccountLoginCommand extends Command
$phoneNumber = $this->ask('Phone number with country code (e.g: +6282112345678)?');
- MadelineProto::sendPhoneCode($phoneNumber);
+ MadelineProto::phoneLogin($phoneNumber);
$code = $this->ask('Phone code?');
try {
- MadelineProto::signIn($code);
+ MadelineProto::completePhoneLogin($code);
} catch (NeedTwoFactorAuthException $e) {
$password = $this->ask("2FA Password (hint '{$e->account->hint}')");
diff --git a/src/Commands/stubs/migration.stub b/src/Commands/stubs/migration.stub
new file mode 100644
index 0000000..b273596
--- /dev/null
+++ b/src/Commands/stubs/migration.stub
@@ -0,0 +1,33 @@
+id();
+ $table->unsignedBigInteger('{{user}}_id');
+ $table->string('session_file');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('{{table}}');
+ }
+}
diff --git a/src/Commands/stubs/telegram_session.stub b/src/Commands/stubs/telegram_session.stub
new file mode 100644
index 0000000..f768525
--- /dev/null
+++ b/src/Commands/stubs/telegram_session.stub
@@ -0,0 +1,26 @@
+database = $manager->connection();
+ $this->table = $table;
+ }
+
+ /**
+ * Get the MadelineProto (session) instance from session table.
+ *
+ * @param int|Model $session can be either id or model instance of TelegramSession which
+ * generated from madeline-proto:multi-session --model command
+ * @param array|null $config if this parameter is null, then the config from telegram.php
+ * file will be used
+ * @return MadelineProto
+ */
+ public function get($session, array $config = null)
+ {
+ if (is_null($config)) {
+ $config = config('telegram.settings');
+ }
+
+ if (is_int($session)) {
+ $session = $this->database->table($this->table)->find($session);
+
+ $sessionFile = $session->session_file;
+ } else {
+ $sessionFile = $session->session_file;
+ }
+
+ return $this->make($sessionFile, $config);
+ }
+
+ /**
+ * Generating MadelineProto (session) instance.
+ *
+ * @param string $sessionFile
+ * @param array $config
+ * @return MadelineProto
+ */
+ public function make(string $sessionFile, array $config)
+ {
+ if (!file_exists(storage_path("app/telegram/"))) {
+ mkdir(storage_path("app/telegram"), 0755);
+ }
+
+ $client = new API(storage_path("app/telegram/$sessionFile"), $config);
+
+ return new MadelineProto($client);
+ }
+}
diff --git a/src/MadelineProto.php b/src/MadelineProto.php
index 9bae347..a372adc 100644
--- a/src/MadelineProto.php
+++ b/src/MadelineProto.php
@@ -40,8 +40,7 @@ class MadelineProto
*
* @param string $code
* @return TelegramObject auth.Authorization
- * @throws NeedTwoFactorAuthException
- * @throws SignUpNeededException
+ * @throws NeedTwoFactorAuthException|SignUpNeededException
*/
public function completePhoneLogin(string $code): TelegramObject
{
@@ -50,10 +49,8 @@ class MadelineProto
switch ($response->return_type) {
case Account::PASSWORD:
throw new NeedTwoFactorAuthException($response);
- break;
case Account::NEED_SIGN_UP:
throw new SignUpNeededException();
- break;
}
return $response;
@@ -142,4 +139,14 @@ class MadelineProto
{
return $this->fullGetSelf() !== false;
}
+
+ /**
+ * Get MadelineProto Message API wrapper instance.
+ *
+ * @return ClientMessages
+ */
+ public function messages()
+ {
+ return new ClientMessages($this->client->messages);
+ }
}
diff --git a/src/MadelineProtoServiceProvider.php b/src/MadelineProtoServiceProvider.php
index 3ed9352..69c8ee9 100644
--- a/src/MadelineProtoServiceProvider.php
+++ b/src/MadelineProtoServiceProvider.php
@@ -2,8 +2,9 @@
namespace Hu\MadelineProto;
-use danog\MadelineProto\API as Client;
+use Hu\MadelineProto\Commands\MultiSessionCommand;
use Hu\MadelineProto\Commands\TelegramAccountLoginCommand;
+use Hu\MadelineProto\Factories\MadelineProtoFactory;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\ServiceProvider;
@@ -16,20 +17,27 @@ class MadelineProtoServiceProvider extends ServiceProvider
*/
public function register()
{
- $this->app->singleton('madeline-proto-client', function () {
- return new Client(config('telegram.session_file'), config('telegram.settings'));
+ $this->app->singleton('madeline-proto-factory', function (Application $app) {
+ return new MadelineProtoFactory($app->make('db'), config('telegram.sessions.multiple.table'));
});
- $this->app->alias('madeline-proto-client', Client::class);
+ $this->app->alias('madeline-proto-factory', MadelineProtoFactory::class);
- $this->app->bind('madeline-proto', function (Application $app) {
- return new MadelineProto($app->make('madeline-proto-client'));
+ //Only for single Telegram session.
+
+ $this->app->singleton('madeline-proto', function (Application $app) {
+ $sessionFactory = $app->make('madeline-proto-factory');
+
+ return $sessionFactory->make(config('telegram.sessions.single.session_file'), config('telegram.settings'));
});
$this->app->alias('madeline-proto', MadelineProto::class);
- $this->app->bind('madeline-proto-messages', function (Application $app) {
- $client = $app->make('madeline-proto-client');
+ $this->app->singleton('madeline-proto-messages', function (Application $app) {
+ $sessionFactory = $app->make('madeline-proto-factory');
- return new ClientMessages($client->messages);
+ return $sessionFactory->make(
+ config('telegram.sessions.single.session_file'),
+ config('telegram.settings')
+ )->messages();
});
$this->app->alias('madeline-proto-messages', ClientMessages::class);
}
@@ -58,7 +66,8 @@ class MadelineProtoServiceProvider extends ServiceProvider
public function registerCommands()
{
$this->commands([
- TelegramAccountLoginCommand::class
+ TelegramAccountLoginCommand::class,
+ MultiSessionCommand::class
]);
}
@@ -69,7 +78,8 @@ class MadelineProtoServiceProvider extends ServiceProvider
{
return [
'madeline-proto',
- 'madeline-proto-client'
+ 'madeline-proto-messages',
+ 'madeline-proto-factory'
];
}
}